﻿'// ========================================================================= '
'// ------------------------------------------------------------------------- '
'//!				\file		vb
'			        \date		june 2010
'			        \author		TNick
'
'			        \brief		
'
'
'   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'   This file is considered universal knowledge. No restrictions
'   are imposed; use as you see fit.
'   Please read ReadMe.txt and Licence.txt in root folder
'   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'
'   The code here implements general application code such as initialization
'   and termination
'// ------------------------------------------------------------------------- '
'// ========================================================================= '
'//
'//
'//
'//
'//  IMPORTS     ------------------------------------------------------------ '
#Region "Imports"

Imports System
Imports Microsoft.Win32
Imports System.Reflection

Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports System.IO
Imports System.Net

'Imports Autodesk.AutoCAD.EditorInput
''Imports Autodesk.AutoCAD.Geometry
'Imports Autodesk.AutoCAD.Customization
''Imports Autodesk.AutoCAD.Colors
''Imports Autodesk.AutoCAD.GraphicsSystem

#End Region
'//  IMPORTS     ============================================================ '
'//
'//
'//
'//
'//  DEFINITIONS    --------------------------------------------------------- '
<Assembly: ExtensionApplication(GetType(CApp))> 
<Assembly: CommandClass(GetType(CApp))> 


'//  DEFINITIONS    ========================================================= '
'//
'//
'//
'//
'//  DATA    ---------------------------------------------------------------- '


'//  DATA    ================================================================ '
'//
'//
'//
'//
'//  CLASS    --------------------------------------------------------------- '
Public Class CApp

#Region "Implementation"
    Implements Autodesk.AutoCAD.Runtime.IExtensionApplication
#End Region

    '// --------------------------------------------------------------------- '
    '// DATA

    #Region "Private variables"
       '// Global variable that tells where this module is located
	    Private sAppPath As String
        '// the registry key used by this application
	    'Private regAppAddInKey As RegistryKey
        '// the registry key used by this application
	    Private Const sTHISAPPNAME As String = "FieldSK_V1"
	    Private Const sUPDATERAPPNAME As String = "FSK_Updater"

	    '// plain old quote
        Private Const QUOTE As String = """"

 		Private regAppAddInKey As RegistryKey = Nothing
        Private regAcadProdKey As RegistryKey = Nothing
        Private regAcadAppKey As RegistryKey = Nothing
        Private acDoc As Document = Nothing

    #End Region

    '// tells that an application should not be loaded (in LOADCTRLS)
    Private Const dDONTLOAD As Long = &H10
    '// tells that an application should be loaded (in LOADCTRLS)
    Private Const dLOAD As Long = 14


    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// structure that describes a versioned file
    Private Structure SVERF
        Dim sFile As String
        Dim lVer As Long
        Dim sBasePath As String
    End Structure
    '// ===================================================================== '

    #Region "ACAD functions"
        Private Declare Auto Function acedPostCommand Lib "acad.exe" _
          Alias "?acedPostCommand@@YAHPB_W@Z" _
          (ByVal strExpr As String) As Integer
        Private Declare Auto Function ads_queueexpr Lib "acad.exe" _
          (ByVal strExpr As String) As Integer
    #End Region




    '// --------------------------------------------------------------------- '
    Private Function GetExceptionString (ByRef ex As System.Exception) as String

	    Dim trace As System.Diagnostics.StackTrace = _
            New System.Diagnostics.StackTrace(ex, True)
	    Dim exceptionLineNumber As Integer =  _
            trace.GetFrame(0).GetFileLineNumber()

        Dim sOut As String = vbNewLine & _
        "---------------------------------------" & vbNewLine & _
        "Exception in updater!!!" & trace.GetFrame(0).GetMethod.Name & vbCrLf & _
	     CStr(ex.Message) & "; " & vbCrLf & _
	     trace.GetFrame(0).ToString & vbCrLf & _
        "---------------------------------------" & vbNewLine

        Return sOut
    End Function
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// tells something to user
    Private Sub InformUser(ByRef sTxt As String)
        Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
        If (acDoc Is Nothing) then
		    MsgBox(sTxt,MsgBoxStyle.OkOnly,"FSK updater program:")
        Else
            acDoc.Editor.WriteMessage(vbNewLine & _
                                      "FSK updater program:" & vbNewLine & _
                                      "    " & sTxt & vbNewLine)
        End If
    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    Private Sub ReportExc(ByRef ex As System.Exception)
        Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
        If acDoc isnot Nothing then
            acDoc.Editor.WriteMessage(GetExceptionString(ex))
        Else
            MsgBox(GetExceptionString(ex))
        End If
    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// sModName - name of the module to make startable
    '// sModPath - path and name of the module to make startable
    '// sDescr - description to be added, if required
    '// regTop - registry key named Applications
    '// dStartSt - value passed as LOADCTRLS
    '// 
    '// return  True for succes
    Private Function Change_Startable_State( _
               ByRef sModName as String, _
               ByRef sModPath as String, _
               ByRef sDescr as String, _
               ByRef regTop As RegistryKey, _
               ByRef dStartSt as long) _
               as Boolean

        Dim bRet As Boolean = False
	    Dim regAppAddInKey As RegistryKey = Nothing
        Try
            If(RegKey_Has(regTop, sModName) = True) Then
            '// registered
				regAppAddInKey = regTop.OpenSubKey(sModName, True)
                regAppAddInKey.SetValue("LOADCTRLS",dStartSt, RegistryValueKind.DWord)
            else
            '// not registered
		        regAppAddInKey = regTop.CreateSubKey(sModName)
		        regAppAddInKey.SetValue("LOADCTRLS", dStartSt, RegistryValueKind.DWord)
			    regAppAddInKey.SetValue("DESCRIPTION", sDescr, RegistryValueKind.String)
			    regAppAddInKey.SetValue("LOADER", sModPath, RegistryValueKind.String)
			    regAppAddInKey.SetValue("MANAGED", 1, RegistryValueKind.DWord)
            End If
            bRet = True
        Catch ex As System.Exception
            ReportExc(ex)
        End Try

        Try
        If bRet = False Then
            Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
            acDoc.Editor.WriteMessage(vbNewLine & _
                "ERROR! Can't change start-up state for " & sModName & vbNewLine)
        End If
        Catch ex As System.Exception
        End Try
        Return bRet
    End Function
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    Private Function Is_Startable( _
            ByRef sModName as String, _
            ByRef regTop As RegistryKey) As Boolean

        Dim bRet As Boolean = False
 		Dim regKey As RegistryKey = Nothing
        Try
            If (RegKey_Has(regAcadAppKey,sModName)) Then
                regKey = regAcadAppKey.OpenSubKey(sModName,False)
                Dim aObj As Object = _
                    regAppAddInKey.GetValue("LOADCTRLS", Nothing)
                If aObj Is Nothing then
                    bRet = False
                Elseif aObj.ToString = dDONTLOAD.ToString Then
                    bRet = False
                Else
                    bRet = True
                End If

                Exit Try

            End If

            bRet = False
        Catch ex As System.Exception
            ReportExc(ex)
        Finally
            If (regKey isnot Nothing) Then
                regKey.Close()
                regKey = Nothing
            End If
        End Try
        Return bRet
    End Function
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    Private Sub Remove_Module( _
            ByRef sModName as String, _
            ByRef regTop As RegistryKey) 

		regTop.DeleteSubKeyTree(sModName)

    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    Private Function RegKey_Has( _
        ByRef rk As RegistryKey, _
        ByRef sStr As String) _
        as Boolean

        Dim bRet As Boolean = False
        Try
            Dim subKeys() As String = rk.GetSubKeyNames()
            Dim sCmp As String = sStr.ToUpper()
            For Each sSubKey As String In subKeys
				If (sSubKey.ToUpper = sCmp) Then
                    bRet = True
                    Exit Try
                End if
            Next
        Catch ex As System.Exception
            ReportExc(ex)
        End Try
        Return bRet
    End Function
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// First stage of the update process
    Private Function Upd_Stage_1() As Boolean
        Dim bRes As Boolean = False
        Dim bSw As Boolean = False
        Try
            if (Change_Startable_State( _
                sTHISAPPNAME, _
                sAppPath & "FSK.dll", _
                sTHISAPPNAME, _
                regAcadAppKey, _
                dDONTLOAD) = False) Then Exit Try
            if (Change_Startable_State( _
                sUPDATERAPPNAME, _
                sAppPath & "FSK_Updater.dll", _
                sUPDATERAPPNAME, _
                regAcadAppKey, _
                dLOAD) = False) Then Exit Try
            bSw = True
            If (Download_Updates() = True) Then
                    Autodesk.AutoCAD.ApplicationServices.Application. _
                        ShowAlertDialog( _
                        "Updates were downloaded, but Autocad needs to be" & vbNewLine & _
                            "restarted to allow update manager to install new files.")

                    Debug.Print("Forcing re-build of CUI file" & vbCrLf)
                    '// remove customistion files
                    Try
                        System.IO.File.Delete(sAppPath & "Misc\UI.cui")
                        System.IO.File.Delete(sAppPath & "Misc\UI.mnr")
                    Catch ex As System.Exception
                        Debug.Print(GetExceptionString(ex))
                    End Try
            Else
                Autodesk.AutoCAD.ApplicationServices.Application. _
                    ShowAlertDialog( _
                    "Updates failed to download")
                bRes = False
                Exit Try
            End If


            bRes = True
        Catch ex As System.Exception
            ReportExc(ex)
        End Try
        If (bRes = False) Then
        If (bSw = True) Then
            Change_Startable_State( _
                sTHISAPPNAME, _
                sAppPath & "FSK.dll", _
                sTHISAPPNAME, _
                regAcadAppKey, _
                dLOAD)
            Remove_Module(sTHISAPPNAME, regAcadAppKey)
        End If
        End If
        Return bRes
    End Function
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// First stage of the update process
    Private Function Upd_Stage_2() As Boolean
        Dim bRes As Boolean = False
        Dim SCrtAry() As SVERF = Nothing
        Try

            if (Change_Startable_State( _
                sTHISAPPNAME, _
                sAppPath & "FSK.dll", _
                sTHISAPPNAME, _
                regAcadAppKey, _
                dLOAD) = False) Then Exit Try
            Remove_Module(sUPDATERAPPNAME, regAcadAppKey)


            '// get an array of files to copy
            If (Get_Ver_Array(sAppPath & "Update\NewFileVer.txt", _
                              Nothing, SCrtAry) = False) Then
                InformUser("Failed to retrieve downloaded data")
                Exit Try
            ElseIf SCrtAry is Nothing Then
                InformUser("Failed to retrieve downloaded data")
                Exit Try
            End If

            '// iterate in all files provided by this array
            For i As Integer = 0 to SCrtAry.Length-1
                Dim sSrc As String = sAppPath & "Update\" & SCrtAry(i).sFile.Replace("\", "_")
                Dim sDest As String = sAppPath & SCrtAry(i).sFile
                If (System.IO.File.Exists(sSrc)) Then
                    If (sSrc.ToUpper() <> "FSK_Updater.dll".ToUpper())
                    Try
                        If (System.IO.File.Exists(sDest) = True) Then
                            System.IO.File.Delete(sDest)
                        End If
                        System.IO.File.Move(sSrc, sDest)
                        
                    Catch ex As System.Exception
                        InformUser("Failed to replace " & vbNewLine & _
                                   sDest & vbNewLine & _
                                   "with" & vbNewLine & _
                                   sSrc)
                    End Try
                    End If
                End If
            Next

            '// we have a new file to tell file versions
            If (System.IO.File.Exists(sAppPath & "FileVer.txt") = True) Then
                System.IO.File.Delete(sAppPath & "FileVer.txt")
            End If
            If (System.IO.File.Exists( sAppPath & "Update\NewFileVer.txt" ) = True) Then
                System.IO.File.Move(sAppPath & "Update\NewFileVer.txt", _
                                    sAppPath & "FileVer.txt")
            End If


            acDoc.SendStringToExecute("FILEDIA 0" & vbCr, _
                                      True, False, False)
            acDoc.SendStringToExecute("NETLOAD " & """" & sAppPath & _
                                      "FSK.dll" & """" & vbCr, _
                                      True, False, False)
            acDoc.SendStringToExecute("FILEDIA 1" & vbCr, _
                                      True, False, False)

            bRes = True
        Catch ex As System.Exception
            ReportExc(ex)
        End Try
        Return bRes
    End Function
    '// ===================================================================== '




    '// --------------------------------------------------------------------- '
    '// called as the application is loading
    Private Sub Initialize() Implements Autodesk.AutoCAD.Runtime.IExtensionApplication.Initialize

        Dim bRes As Boolean

        Debug.Print("FieldSK Updater loaded" & vbCrLf)

		' Get the location of this module
		Dim sAssemblyPath As String = Assembly.GetExecutingAssembly().Location
        Try
            '//
            '//         GENERAL PURPOSE INITIALIZATION
            '//
            acDoc = Application.DocumentManager.MdiActiveDocument
            sAppPath = _
                sAssemblyPath.Substring(0, sAssemblyPath.LastIndexOf("\") + 1)
            Debug.Print("Base path is: " & sAppPath & vbCrLf)

            Debug.Print("Updating..." & vbCrLf)

            ' Get the AutoCAD Applications keys
            Dim sProdKey As String = _
                             HostApplicationServices.Current.RegistryProductRootKey
            Debug.Print("AutoCAD Applications key: " & sProdKey & vbCrLf)

            regAcadProdKey = Registry.CurrentUser.OpenSubKey(sProdKey)
            regAcadAppKey = regAcadProdKey.OpenSubKey("Applications", True)
            If (RegKey_Has(regAcadAppKey,sTHISAPPNAME) = True) Then
				regAppAddInKey = regAcadAppKey.OpenSubKey(sTHISAPPNAME, True)
            End if


            If (RegKey_Has(regAcadAppKey,sUPDATERAPPNAME) = False) Then
            '//
            '//         STAGE 1: we are loaded by main application
            '//
                acDoc.Editor.WriteMessage("FSK is downloading files..." & vbNewLine & _
                                          "Please be patient!" & vbNewLine)
                bRes = Upd_Stage_1()
                Debug.Print("Update stage 1 ended." & vbCrLf)

            Else
            '//
            '//         STAGE 2: we are auto-loaded by Acad
            '//
                bRes = Upd_Stage_2()
                Debug.Print("Update stage 2 ended." & vbCrLf)
                If (bRes = True) Then
                    MsgBox(vbNewLine & vbNewLine & _
                           "FSK was updated" & _
                           vbNewLine & vbNewLine)
                end if
            End if

        Catch ex As System.Exception
            ReportExc(ex)
        Finally
            If (regAcadAppKey IsNot Nothing) Then
                regAcadAppKey.Close()
                regAcadAppKey = Nothing
            End If
            If (regAcadProdKey IsNot Nothing) Then
                regAcadProdKey.Close()
                regAcadProdKey = Nothing
            End If
            If (regAppAddInKey IsNot Nothing) Then
                regAppAddInKey.Close()
                regAppAddInKey = Nothing
            End If
        End Try

        GC.Collect()
        GC.WaitForPendingFinalizers()
    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// called as the application is unloading
    Private Sub Terminate() Implements Autodesk.AutoCAD.Runtime.IExtensionApplication.Terminate

        GC.Collect()
        GC.WaitForPendingFinalizers()
    End Sub
    '// ===================================================================== '


    '// --------------------------------------------------------------------- '
    '// downloads a web file to specified location
    Private Function GetWebFile( _
        ByRef sWeb As String, _
        ByRef sResFile As String) As Boolean

        Dim bRet As Boolean = False
        Try
            System.IO.Directory.CreateDirectory( _
                Path.GetDirectoryName(sResFile))

            Dim wr As HttpWebRequest = _
                CType(WebRequest.Create(sWeb), HttpWebRequest)
            Dim ws As HttpWebResponse = CType(wr.GetResponse(), HttpWebResponse)
            Dim str As Stream = ws.GetResponseStream()
            Dim inBuf(100000) As Byte
            Dim bytesToRead As Integer = CInt(inBuf.Length)
            Dim bytesRead As Integer = 0

            While bytesToRead > 0
                Dim n As Integer = _
                    str.Read(inBuf, bytesRead, bytesToRead)
                If n = 0 Then
                    Exit While
                End If
                bytesRead += n
                bytesToRead -= n
            End While

            Dim fstr As New FileStream( _
                sResFile, _
                FileMode.OpenOrCreate, _
                FileAccess.Write)
            fstr.Write(inBuf, 0, bytesRead)
            str.Close()
            fstr.Close()

            bRet = True
        Catch ex As System.Exception
            bRet = False
            ReportExc(ex)
        End Try

        Return bRet
    End Function
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// reads local file that has informations about files and versions
    Private Function Get_Ver_Array( _
        ByRef sFile As String, _
        ByRef sBaseUrl As String, _
        ByRef SDataO() As SVERF) As Boolean
        '// Update file has following format:
        '// - comments are marked with # and must use a full line; they
        '// are not recognized inside lines or at the end
        '// - field separator is TAB character (inside a line); space is not(!)
        '// recognized as field separator
        '// - BASEURL placed at the start of a line changes the base URL
        '// that is used to locate subsequent(!) files on web; at least a TAB
        '// is required afterwards. Examples of valid input:
        '//     BASEURL =   value
        '//     BASEURL   value
        '// Examples of invalid input:
        '//     BASEURL=    value
        '//     BASEURL =value
        '//     BASEURLvalue
        '// - data lines have the following format:
        '// VERSION<TAB>NAME
        '// where:
        '//     # <TAB> is an actual character
        '//     # VERSION is an integer number in base 10
        '//     # NAME is path inside FSK folder; elements are separated with a \
        '// Example of valid input:
        '//     00000001    FSK.dll
        '//     00000001    Images\IMG_Poly.bmp
        '// To get actual name of the resource, the application will replace 
        '// back-slash characters (\) with an underscore (_)
        Dim bRet As Boolean = False
        Dim sLnTk() As String
        Dim lVer As Long
        Dim srFileReader As System.IO.StreamReader = Nothing
        Dim sSepLst(4) As String
        Dim BaseUrl As String = sBaseUrl

        sSepLst(0) = vbTab
        sSepLst(1) = "--"
        sSepLst(2) = "!"
        sSepLst(3) = "/\"

        Try
            Dim sInputLine As String
            If (System.IO.File.Exists(sFile) = False) Then
                bRet = True
                Exit Try
            End If
            srFileReader = System.IO.File.OpenText(sFile)
            sInputLine = srFileReader.ReadLine()
            Do Until sInputLine Is Nothing
                sLnTk = sInputLine.Split(sSepLst, StringSplitOptions.RemoveEmptyEntries)
                If (sLnTk.Length > 1) Then
                    If (sLnTk(0) Like "[#]*") Then
                        '// this is a comment line
                    ElseIf (sLnTk(0).ToUpper = "BASEURL") Then
                        '// base url is about to change
                        If (sLnTk(1) = "=") Then
                            If (sLnTk.Length > 2) Then
                                BaseUrl = sLnTk(2).Trim()
                            End If
                        Else
                            BaseUrl = sLnTk(1).Trim()
                        End If
                    Else
                        '// this has to be a data line
                        Try
                            lVer = CLng(sLnTk(0))
                            If (SDataO Is Nothing) Then
                                ReDim SDataO(0 To 0)
                            Else
                                ReDim Preserve SDataO(0 To SDataO.Length)
                            End If
                            SDataO(SDataO.Length - 1).lVer = lVer
                            SDataO(SDataO.Length - 1).sBasePath = BaseUrl
                            SDataO(SDataO.Length - 1).sFile = sLnTk(1)
                        Catch ex As System.Exception
                            '// invalid line; skip
                            Debug.Print("Invalid data line found in file " & sFile & vbNewLine & _
                                sInputLine)
                        End Try
                    End If
                End If
                sInputLine = srFileReader.ReadLine()
            Loop

            bRet = True
        Catch ex As System.Exception
            bRet = False
            ReportExc(ex)
        Finally
            If (srFileReader IsNot Nothing) Then
                srFileReader.Close()
            End If
        End Try
        Return bRet
    End Function
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// reads local file that has informations about files and versions
    Private Function Write_Ver_Array( _
        ByRef sFile As String, _
        ByRef SDataO() As SVERF) As Boolean

        Dim srFileReader As System.IO.StreamWriter = Nothing
        Dim bRet As Boolean = False
        Try
            srFileReader = New StreamWriter(sFile)
            For i As Integer = 0 To SDataO.Length - 1
                srFileReader.WriteLine(SDataO(i).lVer.ToString & vbTab & SDataO(i).sFile)
            Next
        Catch ex As System.Exception
            bRet = False
            ReportExc(ex)
        Finally
            If (srFileReader IsNot Nothing) Then
                srFileReader.Close()
            End If
        End Try
        Return bRet
    End Function
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// function that gets update file and parses the content
    Private Function Download_Updates() As Boolean

        Dim bRet As Boolean = False
        Dim sWebUpd As String
        Dim sLocUpd As String = sAppPath & "Update\UpdateHistory.txt"
        Dim sLocBase As String = sAppPath & "FileVer.txt"
        Dim SCrtAry() As SVERF = Nothing
        Dim SNewAry() As SVERF = Nothing
        Dim iCnt As Integer = 0
        Try
            '// get the file
            sWebUpd = CStr( _
                regAppAddInKey.GetValue( _
                "UPDATEFILE", _
                "https://sites.google.com/site/tnickweb/plug-ins/fsk-downloads/UpdateHistory.txt"))

            If (GetWebFile(sWebUpd, sLocUpd) = False) Then
                Exit Try
            End If

            If (Get_Ver_Array(sLocBase, Nothing, SCrtAry) = False) Then
                Exit Try
            End If
            If (Get_Ver_Array(sLocUpd, _
                "https://sites.google.com/site/tnickweb/plug-ins/fsk-downloads/", _
                SNewAry) = False) Then

                Exit Try
            End If
            If (SNewAry Is Nothing) Then
                Exit Try
            End If

            '// we shall iterate in all files and see if we need to get this file
            For i As Integer = 0 To SNewAry.Length - 1
                Dim sCmp As String = SNewAry(i).sFile.ToUpper
                Dim bIsNew As Boolean
                Dim j As Integer
                bIsNew = True
                '// attempt to find it in current list
                If (SCrtAry IsNot Nothing) Then
                    For j = 0 To SCrtAry.Length - 1
                        If (SCrtAry(j).sFile.ToUpper = sCmp) Then
                            '// we have found same file; check version
                            If (SNewAry(i).lVer > SCrtAry(j).lVer) Then
                                bIsNew = False
                                Exit For
                            Else
                                GoTo NextNewFile
                            End If
                        End If
                    Next
                End If
                '// file was not found or our file is older
                acDoc.Editor.WriteMessage("Downloading " & SNewAry(i).sFile & vbNewLine)
                If (GetWebFile(SNewAry(i).sBasePath & _
                                SNewAry(i).sFile.Replace("\"c, "_"c), _
                                sAppPath & "Update\" & SNewAry(i).sFile) = False) Then
                    InformUser("Following file could not be downloaded:" & _
                                     vbNewLine & SNewAry(i).sFile)
                ElseIf bIsNew <> False Then
                    If (SCrtAry Is Nothing) Then
                        ReDim SCrtAry(0 To 0)
                    Else
                        ReDim Preserve SCrtAry(0 To SCrtAry.Length)
                    End If
                    SCrtAry(SCrtAry.Length - 1) = SNewAry(i)
                Else '// bIsNew = False 
                    SCrtAry(j).lVer = SNewAry(i).lVer
                End If
                iCnt = iCnt + 1
NextNewFile:
            Next

            If (iCnt > 0) Then
                '// create the file that will hold current version info
                Write_Ver_Array(sAppPath & "Update\NewFileVer.txt", SCrtAry)
                bRet = True
            End If
        Catch ex As System.Exception
            bRet = False
            ReportExc(ex)
        End Try
        Return bRet
    End Function
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// function that makes updater startable
    Private Function Startable_Updater() As Boolean
        Dim bRet As Boolean = False
        Dim regUpdKey As RegistryKey = Nothing
        Dim sModName As String = "FSK_Updater"
        Try
            ' Get the AutoCAD Applications key
            If (RegKey_Has(regAcadAppKey,sModName) = True) Then

            Else

            End If
            Dim subKeys() As String = regAcadAppKey.GetSubKeyNames()
            For Each sSubKey As String In subKeys
                '' If the updater is already registered
                If (sSubKey = sModName) Then
                    regUpdKey = regAcadAppKey.OpenSubKey(sModName, True)
                    regUpdKey.SetValue("LOADCTRLS", dLOAD, RegistryValueKind.DWord)
                    regAppAddInKey.SetValue("LOADCTRLS", dDONTLOAD, RegistryValueKind.DWord)
                    bRet = True
                    Exit Try
                End If

            Next

            '// not registered
            regUpdKey = regAcadAppKey.CreateSubKey(sModName)
            regUpdKey.SetValue("LOADCTRLS", dLOAD, RegistryValueKind.DWord)
            regUpdKey.SetValue("DESCRIPTION", sModName, RegistryValueKind.String)
            regUpdKey.SetValue("LOADER", sAppPath & "FSK_Updater.dll", RegistryValueKind.String)
            regUpdKey.SetValue("MANAGED", 1, RegistryValueKind.DWord)

            regAppAddInKey.SetValue("LOADCTRLS", dDONTLOAD, RegistryValueKind.DWord)
            bRet = True
        Catch ex As System.Exception
            bRet = False
            ReportExc(ex)
        Finally
            If Not (regAcadAppKey Is Nothing) Then regAcadAppKey.Close()
            If Not (regAcadProdKey Is Nothing) Then regAcadProdKey.Close()
            If Not (regUpdKey Is Nothing) Then regUpdKey.Close()
        End Try
        Return bRet
    End Function
    '// ===================================================================== '


End Class 
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


'//  CLASS    =============================================================== '
'//
'//
'//
'//
'//  FUNCTIONS    ----------------------------------------------------------- '

'//  FUNCTIONS    =========================================================== '
'//
'//
'//
'//
'// ------------------------------------------------------------------------- '
'// ========================================================================= '


    'Private sFList() As string = { _
    '    "FSK.dll", _
    '    "FSK.pdb", _
    '    "FSK_XL.dll", _
    '    "FSK_XL.pdb", _
    '    "FSK_XL00.dll", _
    '    "FSK_XL00.pdb", _
    '    "FSK_XL11.dll", _
    '    "FSK_XL11.pdb", _
    '    "FSK_XL12.dll", _
    '    "FSK_XL12.pdb"}


            ' '' ''// remove old files
            '' ''Debug.Print("Removing old files...")
            '' ''For i As Integer = 0 To UBound(sFList)
            '' ''    Try
            '' ''        Debug.Print("  Deleting " & sAppPath & sFList(i) & vbCrLf)
            '' ''        System.IO.File.Delete(sAppPath & sFList(i))
            '' ''    Catch ex As System.Exception
            '' ''        Debug.Print(sFList(i) & " was not deleted")
            '' ''        Debug.Print(GetExceptionString(ex))
            '' ''    End Try
            '' ''Next i


            ' '' '' ''// make shure that we have the update data

            '' '' ''bRes = True
            '' '' ''If System.IO.Directory.Exists(sAppPath & "Update") = False Then
            '' '' ''    bRes = False
            '' '' ''    acDoc.Editor.WriteMessage(vbNewLine & _
            '' '' ''        "ERROR! FSK Updater failed to run! Update folder was not found." & vbNewLine)
            '' '' ''Else
            '' '' ''    For i As Integer = 0 To UBound(sFList)
            '' '' ''        If System.IO.File.Exists(sAppPath & "Update\" & sFList(i)) = False Then
            '' '' ''            acDoc.Editor.WriteMessage(vbNewLine & _
            '' '' ''                "ERROR! FSK Updater failed to run!" & vbNewLine & _
            '' '' ''                "A required component (" & sFList(i) & ") was not found." & vbNewLine)
            '' '' ''            bRes = False
            '' '' ''            Exit For
            '' '' ''        End If
            '' '' ''    Next
            '' '' ''End If
            '' '' ''If (bRes = False) Then
            '' '' ''    Exit Try
            '' '' ''End If




            '' '' ''If (Is_Startable(sTHISAPPNAME, regAcadAppKey) = True) Then
            '' '' ''    Debug.Print("Main application is startable" & vbCrLf)

            '' '' ''    Change_Startable_State( _
            '' '' ''        sTHISAPPNAME, _
            '' '' ''        sAppPath & "FSK.dll", _
            '' '' ''        sTHISAPPNAME, _
            '' '' ''        regAcadAppKey, _
            '' '' ''        dDONTLOAD)
            '' '' ''    '// the key should have been removed
            '' '' ''    '// if it's not removed, we can't overwrite the dll
            '' '' ''    acDoc.Editor.WriteMessage(vbNewLine & _
            '' '' ''        "ERROR! FSK Updater failed to run because proper initialization" & vbNewLine & _
            '' '' ''        "was not performed. To make a second attempt, please restart Autocad." & vbNewLine)
            '' '' ''    '// this module may have been started with a NETLOAD command
            '' '' ''    '// enshure that it will be started next time
            '' '' ''    Change_Startable_State( _
            '' '' ''        sUPDATERAPPNAME, _
            '' '' ''        Assembly.GetExecutingAssembly().Location, _
            '' '' ''        sUPDATERAPPNAME, _
            '' '' ''        regAcadAppKey, _
            '' '' ''        dLOAD)
            '' '' ''Else
            '' '' ''    Debug.Print("Main application is not startable" & vbCrLf)
            '' '' ''    '// make shure that next time we will not be loaded
            '' '' ''    'Change_Startable_State( _
            '' '' ''    '    sUPDATERAPPNAME, _
            '' '' ''    '    Assembly.GetExecutingAssembly().Location, _
            '' '' ''    '    sUPDATERAPPNAME, _
            '' '' ''    '    regAcadAppKey, _
            '' '' ''    '    dDONTLOAD)
            '' '' ''    Remove_Module(sUPDATERAPPNAME, regAcadAppKey)


            '' '' ''    '// copy files from update folder
            '' '' ''    Debug.Print("Copying new files ...")
            '' '' ''    For i As Integer = 0 To UBound(sFList)
            '' '' ''        Debug.Print("  copy " & sAppPath & "Update\" & sFList(i) & vbCrLf)
            '' '' ''        Try
            '' '' ''            System.IO.File.Copy(sAppPath & "Update\" & sFList(i), sAppPath & sFList(i))
            '' '' ''        Catch ex As System.Exception
            '' '' ''            acDoc.Editor.WriteMessage(vbNewLine & _
            '' '' ''                "ERROR! FSK Updater failed because " & vbNewLine & _
            '' '' ''                sFList(i) & " could not be updated." & vbNewLine)
            '' '' ''        End Try
            '' '' ''    Next i

            '' '' ''    '// update image folder, as required
            '' '' ''    If (System.IO.Directory.Exists(sAppPath & "Update\Images")) Then
            '' '' ''        Debug.Print("Adding new images ...")
            '' '' ''        For Each sFile As String In _
            '' '' ''            System.IO.Directory.GetFiles(sAppPath & "Update\Images")
            '' '' ''            Debug.Print("  file " & sAppPath & "Images\" & sFile & vbCrLf)

            '' '' ''            If System.IO.File.Exists(sAppPath & "Images\" & sFile) Then
            '' '' ''                System.IO.File.Delete(sAppPath & "Images\" & sFile)
            '' '' ''            End If
            '' '' ''            System.IO.File.Copy( _
            '' '' ''                sAppPath & "Update\Images\" & sFile, _
            '' '' ''                sAppPath & "Images\" & sFile)
            '' '' ''        Next
            '' '' ''    End If


            '' '' ''    '// update aditional binaries, as required
            '' '' ''    '// WARNING!!!!! WARNING!!!!! WARNING!!!!! WARNING!!!!! WARNING!!!!!
            '' '' ''    '// This may be regarded as a security breach
            '' '' ''    '// a way to disable it is provided
            '' '' ''    '// WARNING!!!!! WARNING!!!!! WARNING!!!!! WARNING!!!!! WARNING!!!!! 
            '' '' ''    Debug.Print("Updating binaries...")
            '' '' ''    Dim disUB As String = regAppAddInKey.GetValue("Disable_binaries_update", "0").ToString
            '' '' ''    If (disUB = "0") Then
            '' '' ''        Debug.Print("...allowed")
            '' '' ''        If (System.IO.Directory.Exists(sAppPath & "Update\Binaries")) Then
            '' '' ''            If Not (System.IO.Directory.Exists(sAppPath & "Binaries")) Then
            '' '' ''                System.IO.Directory.CreateDirectory(sAppPath & "Binaries")
            '' '' ''            End If
            '' '' ''            For Each sFile As String In _
            '' '' ''                System.IO.Directory.GetFiles(sAppPath & "Update\Binaries")

            '' '' ''                Debug.Print("  file " & sAppPath & "Binaries\" & sFile & vbCrLf)

            '' '' ''                If System.IO.File.Exists(sAppPath & "Binaries\" & sFile) Then
            '' '' ''                    System.IO.File.Delete(sAppPath & "Binaries\" & sFile)
            '' '' ''                End If
            '' '' ''                System.IO.File.Copy( _
            '' '' ''                    sAppPath & "Update\Binaries\" & sFile, _
            '' '' ''                    sAppPath & "Binaries\" & sFile)
            '' '' ''                Change_Startable_State( _
            '' '' ''                    sFile, _
            '' '' ''                    sAppPath & "Binaries\" & sFile, _
            '' '' ''                    sFile, _
            '' '' ''                    regAcadAppKey, _
            '' '' ''                    dLOAD)
            '' '' ''            Next
            '' '' ''        End If
            '' '' ''    End If
            '' '' ''    '// WARNING!!!!! WARNING!!!!! WARNING!!!!! WARNING!!!!! WARNING!!!!! 
            '' '' ''    '// WARNING!!!!! WARNING!!!!! WARNING!!!!! WARNING!!!!! WARNING!!!!! 


            '' '' ''    '// make shure that next time proper library will be loaded
            '' '' ''    Change_Startable_State( _
            '' '' ''        sTHISAPPNAME, _
            '' '' ''        sAppPath & "FSK.dll", _
            '' '' ''        sTHISAPPNAME, _
            '' '' ''        regAcadAppKey, _
            '' '' ''        dLOAD)
            '' '' ''End If
